home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * PARSE.C
- *
- * Parse the next token or tokens
- */
-
- #include "defs.h"
- #include <stdarg.h>
- #ifndef AMIGA
- #include <suplib/string.h>
- #endif
-
- Prototype void InitParser(void);
- Prototype void ParseFile(char *);
- Prototype token_t ParseAssignment(char *, token_t);
- Prototype token_t ParseDependency(char *, token_t);
- Prototype token_t GetElement(void);
- Prototype token_t XGetElement(void);
- Prototype void ParseVariable(List *, short);
- Prototype char *ParseVariableBuf(List *, ubyte *, short);
- Prototype char *ExpandVariable(ubyte *, List *);
- Prototype token_t GetToken(void);
- Prototype void expect(token_t, token_t);
- Prototype void error(short, const char *, ...);
-
-
- Prototype char SymBuf[256];
- Prototype long LineNo;
-
- char SpecialChar[256];
- char SChars[] = { ":=()\n\\\" \t\r\014" };
- char SymBuf[256];
- char AltBuf[256];
- char AltBuf2[256];
- long LineNo = 1;
- char *FileName = "";
- FILE *Fi;
-
- void
- InitParser()
- {
- short i;
- for (i = 0; SChars[i]; ++i)
- SpecialChar[(ubyte)SChars[i]] = 1;
- }
-
- /*
- * Parse lines as follows:
- *
- * symbol = ...
- * symbol ... : symbol ...
- * (commands, begin with tab or space)
- * (blank line)
- *
- *
- */
-
- void
- ParseFile(fileName)
- char *fileName;
- {
- FILE *fi;
- token_t t;
-
- if ((fi = fopen(fileName, "r")) == NULL)
- error(FATAL, "Unable to open %s", fileName);
- FileName = strdup(fileName);
- Fi = fi;
-
- for (t = GetElement(); t; ) {
- switch(t) {
- case TokNewLine:
- t = GetElement();
- break;
- case TokSym:
- strcpy(AltBuf2, SymBuf);
-
- /*
- * check for '=' -- assignment
- */
-
- t = GetElement();
- if (t == TokEq)
- t = ParseAssignment(AltBuf2, t);
- else
- t = ParseDependency(AltBuf2, t);
- break;
- default:
- error(FATAL, "Expected a symbol!");
- break;
- }
- }
- }
-
- /*
- * Parse an asignment. Parsed as-is (late eval)
- *
- * t contains TokEq, ignore
- */
-
- token_t
- ParseAssignment(char *varName, token_t t)
- {
- Var *var = MakeVar(varName, '$');
- long len;
- short done;
- short eol = 1;
- List tmpList;
-
- NewList(&tmpList);
-
- #ifdef NOTDEF
- {
- short c;
- while ((c = fgetc(Fi)) == ' ' || c == '\t')
- ;
- if (c != EOF)
- ungetc(c, Fi);
- }
- #endif
-
- while (fgets(AltBuf, sizeof(AltBuf), Fi)) {
- len = strlen(AltBuf);
-
- if (eol && AltBuf[0] == '#') {
- ++LineNo;
- continue;
- }
- if (len && AltBuf[len-1] == '\n') {
- ++LineNo;
- --len;
- if (len && AltBuf[len-1] == '\\') {
- --len;
- done = 0;
- } else {
- done = 1;
- }
- eol = 1;
- } else {
- done = 0;
- eol = 0;
- }
- AltBuf[len] = 0;
- {
- long i;
-
- for (i = 0; i < len && (AltBuf[i] == ' ' || AltBuf[i] == '\t'); ++i)
- ;
- for ( ; i < len; ++i)
- PutCmdListChar(&tmpList, AltBuf[i]);
- }
- if (done > 0)
- break;
- }
-
- /*
- * Now, load temp list into buffer and expand into the variable
- */
-
- {
- char *buf = malloc(CmdListSize(&tmpList) + 1);
- CopyCmdListBuf(&tmpList, buf);
- ExpandVariable(buf, &tmpList);
- AppendCmdList(&tmpList, &var->var_CmdList);
- free(buf);
- }
- return(GetElement());
- }
-
- /*
- * Parse a dependency
- */
-
- token_t
- ParseDependency(char *firstSym, token_t t)
- {
- DepRef *lhs;
- DepRef *rhs;
- List lhsList;
- List rhsList;
- List *cmdList = malloc(sizeof(List));
- long nlhs = 0;
- long nrhs = 0;
- short ncol = 0;
-
- NewList(cmdList);
- NewList(&lhsList);
- NewList(&rhsList);
-
- ++nlhs;
- for (CreateDepRef(&lhsList, firstSym); t != TokColon; t = GetElement()) {
- expect(t, TokSym);
- CreateDepRef(&lhsList, SymBuf);
- ++nlhs;
- }
- t = GetElement();
- if (t == TokColon) {
- ++ncol;
- t = GetElement();
- }
-
- while (t != TokNewLine) {
- expect(t, TokSym);
- CreateDepRef(&rhsList, SymBuf);
- ++nrhs;
- t = GetElement();
- }
-
- /*
- * parse command list
- */
-
- {
- short c;
- short blankLine = 1;
- short ws = 0; /* white space skip */
-
- while ((c = getc(Fi)) != EOF) {
- if (c == '\n') {
- ++LineNo;
- if (blankLine)
- break;
- PutCmdListChar(cmdList, '\n');
- blankLine = 1;
- continue;
- }
-
- switch(c) {
- case ' ':
- case '\t':
- if (blankLine) { /* remove all but one ws after nl */
- ws = 1;
- continue;
- }
- PutCmdListChar(cmdList, c);
- break;
- case '\\':
- if (ws) {
- PutCmdListChar(cmdList, ' ');
- ws = 0;
- }
- c = getc(Fi);
- if (c == '\n') {
- blankLine = 1;
- ++LineNo;
- continue;
- }
- PutCmdListChar(cmdList, '\\');
- PutCmdListChar(cmdList, c);
- break;
- default:
- if (ws) {
- PutCmdListChar(cmdList, ' ');
- ws = 0;
- }
- PutCmdListChar(cmdList, c);
- break;
- }
- blankLine = 0;
- }
- }
- dbprintf(("parse: %d : %d\n", nlhs, nrhs));
-
- /*
- * formats allowed:
- *
- * X :: Y each item depends on all items (X x Y dependancies)
- * 1 : N item depends on items
- * N : N 1:1 map item to item
- * N : 1 items depend on item
- */
-
- if (ncol == 1) {
- while (lhs = RemHead(&lhsList)) {
- if (GetHead(&lhsList)) {
- for (rhs = GetHead(&rhsList); rhs; rhs = GetSucc(&rhs->rn_Node))
- IncorporateDependency(lhs, DupDepRef(rhs), cmdList);
- } else {
- while (rhs = RemHead(&rhsList))
- IncorporateDependency(lhs, rhs, cmdList);
- }
- IncorporateDependency(lhs, NULL, cmdList);
- free(lhs);
- }
- } else if (nlhs == 1) {
- lhs = RemHead(&lhsList);
- while (rhs = RemHead(&rhsList))
- IncorporateDependency(lhs, rhs, cmdList);
- IncorporateDependency(lhs, NULL, cmdList);
- free(lhs);
- } else if (nrhs == 1) {
- rhs = RemHead(&rhsList);
- while (lhs = RemHead(&lhsList)) {
- IncorporateDependency(lhs, rhs, cmdList);
- free(lhs);
- }
- } else if (nlhs == nrhs) {
- while ((lhs = RemHead(&lhsList)) && (rhs = RemHead(&rhsList))) {
- IncorporateDependency(lhs, rhs, cmdList);
- free(lhs);
- }
- } else {
- error(FATAL, "%d items on the left, %d on the right of colon!", nlhs, nrhs);
- }
- return(t);
- }
-
- /*
- * GetElement() - return a token after variable/replace parsing
- */
-
- #ifdef NOTDEF
- token_t
- GetElement(void)
- {
- token_t t = XGetElement();
- return(t);
- }
- #endif
-
- token_t
- GetElement(void)
- {
- static List CmdList = { (Node *)&CmdList.lh_Tail, NULL, (Node *)&CmdList.lh_Head };
- token_t t;
- short c;
-
- top:
- if (PopCmdListSym(&CmdList, SymBuf, sizeof(SymBuf)) == 0) {
- return(TokSym);
- }
-
- t = GetToken();
- swi:
- switch(t) {
- case TokDollar:
- case TokPercent:
- c = fgetc(Fi);
- if (c == '(') {
- ParseVariable(&CmdList, (t == TokPercent) ? '%' : '$');
-
- /*
- * XXX how to handle dependancies verses nominal string concat?
- */
-
- while ((c = fgetc(Fi)) != ' ' && c != '\t' && c != '\n' && c != ':') {
- if (c == EOF)
- break;
- if (c == '$') {
- t = TokDollar;
- goto swi;
- }
- if (c == '%') {
- t = TokPercent;
- goto swi;
- }
- PutCmdListChar(&CmdList, c);
- }
- if (c != EOF)
- ungetc(c, Fi);
- goto top;
- }
- ungetc(c, Fi);
- default:
- break;
- }
- return(t);
- }
-
- /*
- * ParseVariable() - parse a variable reference, expanding it into a
- * command list. Fi begins at the first character in the variable name
- *
- * $(NAME)
- * $(NAME:"from":"to")
- *
- */
-
- void
- ParseVariable(List *cmdList, short c0)
- {
- short c;
- short i = 0;
- Var *var;
-
- /*
- * variable name
- */
-
- while ((c = getc(Fi)) != EOF && !SpecialChar[c])
- AltBuf[i++] = c;
- AltBuf[i] = 0;
-
- var = FindVar(AltBuf, c0);
- if (var == NULL)
- error(FATAL, "Variable %s does not exist", AltBuf);
-
- dbprintf(("ParseVariable: (%c:%c) %s\n", c0, c, AltBuf));
-
- /*
- * now, handle modifiers
- */
-
- if (c == ')') {
- CopyCmdList(&var->var_CmdList, cmdList);
- return;
- }
- if (c != ':')
- error(FATAL, "Bad variable specification after name");
-
- /*
- * source operation
- */
-
- c = fgetc(Fi);
- if (c == '\"') {
- ungetc(c, Fi);
- expect(GetToken(), TokStr);
- c = fgetc(Fi);
- } else {
- i = 0;
- while (c != ')' && c != ':' && c != EOF) {
- SymBuf[i++] = c;
- c = fgetc(Fi);
- }
- SymBuf[i] = 0;
- }
-
- strcpy(AltBuf, SymBuf);
-
- /*
- * destination operation
- */
-
- if (c == ')') {
- CopyCmdListConvert(&var->var_CmdList, cmdList, AltBuf, AltBuf);
- return;
- }
-
- if (c != ':')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
- c = fgetc(Fi);
- if (c == '\"') {
- ungetc(c, Fi);
- expect(GetToken(), TokStr);
- c = fgetc(Fi);
- } else {
- i = 0;
- while (c != ')' && c != ':' && c != EOF) {
- SymBuf[i++] = c;
- c = fgetc(Fi);
- }
- SymBuf[i] = 0;
- }
-
- if (c != ')')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
- CopyCmdListConvert(&var->var_CmdList, cmdList, AltBuf, SymBuf);
- }
-
- /*
- * Since this is recursively called we have to save/restore oru temporary
- * bufferse (SymBuf & AltBuf). the buf pointer may itself be pointing
- * into these but we are ok since it is guarenteed >= our copy destination
- * as we index through it.
- */
-
-
- char *
- ParseVariableBuf(List *cmdList, ubyte *buf, short c0)
- {
- short c;
- short i = 0;
- Var *var;
- char *symBuf = AllocPathBuffer();
- char *altBuf = AllocPathBuffer();
-
- dbprintf(("ParseVariableBuf: (%c) %s\n", c0, buf));
- /*
- * variable name
- */
-
- while ((c = *buf++) && !SpecialChar[c])
- altBuf[i++] = c;
- altBuf[i] = 0;
-
- var = FindVar(altBuf, c0);
- if (var == NULL)
- error(FATAL, "Variable %s does not exist", altBuf);
-
- /*
- * now, handle modifiers
- */
-
- if (c == ')') {
- CopyCmdList(&var->var_CmdList, cmdList);
- FreePathBuffer(symBuf);
- FreePathBuffer(altBuf);
- return(buf);
- }
- if (c != ':')
- error(FATAL, "Bad variable specification after name");
-
- /*
- * source operation
- */
-
- c = *buf++;
-
- if (c == '\"') {
- i = 0;
- while ((c = *buf++) && c != '\"')
- symBuf[i++] = c;
- if (c == '\"')
- c = *buf++;
- } else {
- i = 0;
- while (c && c != ')' && c != ':') {
- symBuf[i++] = c;
- c = *buf++;
- }
- }
-
- symBuf[i] = 0;
- strcpy(altBuf, symBuf);
-
- /*
- * destination operation
- */
-
- if (c == ')') {
- CopyCmdListConvert(&var->var_CmdList, cmdList, altBuf, symBuf);
- FreePathBuffer(symBuf);
- FreePathBuffer(altBuf);
- return(buf);
- }
-
- if (c != ':')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
- c = *buf++;
-
- if (c == '\"') {
- i = 0;
- while ((c = *buf++) && c != '\"')
- symBuf[i++] = c;
- if (c == '\"')
- c = *buf++;
- } else {
- i = 0;
- while (c && c != ')' && c != ':') {
- symBuf[i++] = c;
- c = *buf++;
- }
- }
- symBuf[i] = 0;
-
- if (c != ')')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
- dbprintf(("CopyConvert to %s %s (%s) %08lx\n", altBuf, symBuf, var->var_Node.ln_Name, GetHead(&var->var_CmdList)));
-
- CopyCmdListConvert(&var->var_CmdList, cmdList, altBuf, symBuf);
- FreePathBuffer(symBuf);
- FreePathBuffer(altBuf);
- return(buf);
- }
-
- char *
- ExpandVariable(buf, list)
- ubyte *buf;
- List *list;
- {
- short c;
- short n = 0;
- short tmpListValid;
- short keepInList;
- List tmpList;
- static int Levels;
-
- if (++Levels == 20)
- error(FATAL, "Too many levels of variable recursion");
-
- if (list) {
- keepInList = 1;
- tmpListValid = 1;
- } else {
- keepInList = 0;
- tmpListValid = 0;
- list = &tmpList;
- NewList(list);
- }
-
- while (c = buf[n]) {
- if (c == '$' || c == '%') {
- if (buf[n+1] == '(') {
- if (tmpListValid == 0) {
- int i;
-
- for (i = 0; i < n; ++i)
- PutCmdListChar(list, buf[i]);
- tmpListValid = 1;
- }
- n = (ubyte *)ParseVariableBuf(list, buf + n + 2, c) - buf;
- } else if (buf[n+1] == c) {
- if (tmpListValid)
- PutCmdListChar(list, c);
- n += 2;
- } else {
- if (tmpListValid)
- PutCmdListChar(list, c);
- ++n;
- }
- } else {
- if (tmpListValid)
- PutCmdListChar(list, c);
- ++n;
- }
- }
- if (keepInList == 0) {
- if (tmpListValid) {
- buf = malloc(CmdListSize(list) + 1);
- CopyCmdListBuf(list, buf);
- }
- }
- --Levels;
- return(buf);
- }
-
-
- #ifdef NOTDEF
-
- short c;
- short i;
- Var *var;
-
- /*
- * variable name
- */
-
- while (c = *buf++ && !SpecialChar[c])
- AltBuf[i++] = c;
-
- AltBuf[i] = 0;
-
- var = FindVar(AltBuf, c0);
- if (var == NULL)
- error(FATAL, "Variable %s does not exist", AltBuf);
-
- /*
- * now, handle modifiers
- */
-
- if (c == ')') {
- CopyCmdList(&var->var_CmdList, cmdList);
- return;
- }
- if (c != ':')
- error(FATAL, "Bad variable specification after name");
-
- /*
- * source operation
- */
-
- c = fgetc(Fi);
- if (c == '\"') {
- ungetc(c, Fi);
- expect(GetToken(), TokStr);
- c = fgetc(Fi);
- } else {
- i = 0;
- while (c != ')' && c != ':' && c != EOF) {
- SymBuf[i++] = c;
- c = fgetc(Fi);
- }
- }
- SymBuf[i] = 0;
-
- strcpy(AltBuf, SymBuf);
-
- /*
- * destination operation
- */
-
- if (c == ')') {
- CopyCmdListConvert(&var->var_CmdList, cmdList, AltBuf, SymBuf);
- return;
- }
-
- if (c != ':')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
-
- c = fgetc(Fi);
- if (c == '\"') {
- ungetc(c, Fi);
- expect(GetToken(), TokStr);
- c = fgetc(Fi);
- } else {
- i = 0;
- while (c != ')' && c != ':' && c != EOF) {
- SymBuf[i++] = c;
- c = fgetc(Fi);
- }
- }
-
- if (c != ')')
- error(FATAL, "Bad variable replacement spec: %c", c);
-
- CopyCmdListConvert(&var->var_CmdList, cmdList, AltBuf, SymBuf);
- }
-
- #endif
-
-
- /*
- * GetToken() - return a single token
- */
-
- #ifdef NOTDEF
- token_t
- GetToken()
- {
- token_t t;
- printf("get ");
- fflush(stdout);
- t = XGetToken();
- printf("token %d\n", t);
- return(t);
- }
- #endif
-
- token_t
- GetToken()
- {
- short c;
- short i;
-
- for (;;) {
- switch(c = getc(Fi)) {
- case EOF:
- return(0);
- case ':':
- return(TokColon);
- case '=':
- return(TokEq);
- case '\n':
- ++LineNo;
- return(TokNewLine);
- case '(':
- return(TokOpenParen);
- case ')':
- return(TokCloseParen);
- case '$':
- return(TokDollar);
- case '%':
- return(TokPercent);
- case ' ':
- case '\t':
- case '\014':
- case '\r':
- break;
- case '#':
- while ((c = getc(Fi)) != EOF) {
- if (c == '\n') {
- ++LineNo;
- break;
- }
- }
- break;
- case '\"':
- for (i = 0; i < sizeof(SymBuf) - 1 && (c = fgetc(Fi)) != EOF; ++i) {
- if (c == '\n')
- error(FATAL, "newline in control string");
- if (c == '\"')
- break;
- if (c == '\\')
- c = fgetc(Fi);
- SymBuf[i] = c;
- }
- SymBuf[i] = 0;
- if (i == sizeof(SymBuf) - 1)
- error(FATAL, "Symbol overflow: %s", SymBuf);
- if (c != '\"')
- error(FATAL, "Expected closing quote");
- return(TokStr);
- case '\\':
- c = fgetc(Fi);
- if (c == '\n') {
- ++LineNo;
- break;
- }
- /* fall through */
- default:
- SymBuf[0] = c;
-
- for (i = 1; i < sizeof(SymBuf) - 1 && (c = getc(Fi)) != EOF; ++i) {
- if (SpecialChar[c]) {
- ungetc(c, Fi);
- break;
- }
- SymBuf[i] = c;
- }
- SymBuf[i] = 0;
- if (i == sizeof(SymBuf) - 1)
- error(FATAL, "Symbol overflow: %s", SymBuf);
- return(TokSym);
- }
- }
- }
-
- void
- expect(token_t tgot, token_t twant)
- {
- if (tgot != twant)
- error(FATAL, "Unexpected token");
- }
-
- void
- error(short type, const char *ctl, ...)
- {
- static char *TypeString[] = { "Fatal", "Warning", "Debug" };
- static char ExitAry[] = { 1, 0, 0 };
- va_list va;
-
- printf("%s: %s Line %d: ", FileName, TypeString[type], LineNo);
- va_start(va, ctl);
- vprintf(ctl, va);
- va_end(va);
- puts("");
- if (ExitAry[type])
- exit(20);
- }
-
-